package com.usoft.example.search;

import com.usoft.grpc.example.search.SearchRequest;
import com.usoft.grpc.example.search.SearchResponse;
import com.usoft.grpc.example.search.SearchServiceGrpc;
import io.grpc.CallOptions;
import io.grpc.Channel;
import io.grpc.ClientCall;
import io.grpc.ClientInterceptor;
import io.grpc.ForwardingClientCall;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.Metadata;
import io.grpc.MethodDescriptor;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Created by xinxingegeya on 15/12/17.
 */
public class SearchClientTest {
    private static final Logger logger = Logger
        .getLogger(SearchClientTest.class.getName());

    private String address = "127.0.0.1";
    private int port = 8888;

    private ManagedChannel channel;
    private SearchServiceGrpc.SearchServiceBlockingStub blockingStub;
    private SearchServiceGrpc.SearchServiceStub asyncStub;

    @Before
    public void setup() {
        channel = ManagedChannelBuilder.forAddress(address, port)
            .usePlaintext(true).build();
        blockingStub = SearchServiceGrpc.newBlockingStub(channel);
        asyncStub = SearchServiceGrpc.newStub(channel);

    }

    @After
    public void shutdown() throws InterruptedException {
        channel.shutdown().awaitTermination(5, TimeUnit.SECONDS);
    }

    @Test
    public void test11() {

        final Metadata.Key<String> credKey = Metadata.Key.of("Cred",
            Metadata.ASCII_STRING_MARSHALLER);

        int pageNo = 12;
        int pageSize = 12;

        logger.info("search param pageNo=" + pageNo + ",pageSize=" + pageSize);
        try {
            SearchRequest request = SearchRequest.newBuilder()
                .setPageNumber(pageNo).setResultPerPage(pageSize)
                .setQuery("hello world").build();

            SearchResponse response = blockingStub
                .withInterceptors(new ClientInterceptor() {
                    @Override
                    public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
                            MethodDescriptor<ReqT, RespT> method,
                            CallOptions callOptions, Channel next) {
                        ClientCall<ReqT, RespT> call = next.newCall(method,
                            callOptions);

                        logger.info("The MethodDescriptor="
                            + method.getFullMethodName());
                        logger.info("Authority CallOption="
                            + callOptions.getAuthority());
                        logger.info("");

//                        while (!channel.isTerminated()) {
//                            logger.info("channel isTerminated====");
//                            try {
//                                channel.awaitTermination(1000,
//                                    TimeUnit.MILLISECONDS);
//                            } catch (InterruptedException e) {
//                                e.printStackTrace();
//                            }
//                        }

                        logger.info("interceptCall");
                        return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(
                            call) {
                            @Override
                            public void start(
                                    ClientCall.Listener<RespT> responseListener,
                                    Metadata headers) {
                                logger.info(
                                    "ForwardingClientCall.SimpleForwardingClientCall.start");
                                headers.put(credKey, "abcd");
                                logger.info("the header Cred = "
                                    + headers.get(credKey));

                                super.start(responseListener, headers);
                            }
                        };
                    }
                }).searchWithSimpleRpc(request);

            logger.info("search result: " + response.toString());
        } catch (RuntimeException e) {
            logger.log(Level.WARNING, "RPC failed", e);
            return;
        }
    }
}
